package com.sky.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.WebSocketServer.WebSocketServer;
import com.sky.context.UserHolder;
import com.sky.dto.OrdersConfirmDTO;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersPaymentDTO;
import com.sky.dto.OrdersRejectionDTO;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.BusinessException;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrdersMapper;
import com.sky.result.PageBean;
import com.sky.service.AddressBookService;
import com.sky.service.OrderService;
import com.sky.service.ShoppingCartService;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequiredArgsConstructor  //由lombok提供,替代@Autowired  但是需要使用final修饰注入的属性
@Service
@Transactional
public class OrderServiceImpl implements OrderService {

    private final WebSocketServer webSocketServer;


    private final OrdersMapper ordersMapper;

    private final OrderDetailMapper orderDetailMapper;

    private final AddressBookService addressBookService;

    private final ShoppingCartService shoppingCartService;

    //用户下单
    @Override
    public OrderSubmitVO save(Orders orders) {

        // 1.根据收货人id查询地址信息
        AddressBook addressBook = addressBookService.findById(orders.getAddressBookId());
        if (addressBook == null) {
            throw new RuntimeException("请选择收货地址");
        }
        // 2.根据登录用户id查询购物车信息
        List<ShoppingCart> shoppingCartList = shoppingCartService.findList();
        if (CollectionUtil.isEmpty(shoppingCartList)) {
            throw new RuntimeException("购物车为空");
        }
        // 3.保存订单
        // 3-1补齐参数
        orders.setNumber(IdUtil.simpleUUID());//订单号:自己生成要求唯一(不能大于32位)
        orders.setStatus(1);//订单状态,待付款
        orders.setUserId(UserHolder.get());//下单人id
        orders.setOrderTime(LocalDateTime.now());//下单时间
        orders.setPayStatus(0);//支付状态,未支付
        orders.setPhone(addressBook.getPhone());//下单人手机号
        orders.setAddress(addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());//收货地址
        orders.setConsignee(addressBook.getConsignee());

        // 3-2调用mapper保存
        ordersMapper.save(orders);
        // 4.保存订单详情
        // 4-1遍历购物车,得到购物项
        for (ShoppingCart shoppingCart : shoppingCartList) {
            //4-2 购物项--订单详情（忽略id）
            OrderDetail orderDetail = BeanUtil.copyProperties(shoppingCart, OrderDetail.class, "id");
            //4-3 补齐订单id
            orderDetail.setOrderId(orders.getId());
            //4-4 保存订单详情
            orderDetailMapper.save(orderDetail);
        }

        // 5.清空当前购物车
        shoppingCartService.clean();
        // 6.返回vo
        OrderSubmitVO build = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderTime(orders.getOrderTime())
                .orderAmount(orders.getAmount())

                .build();
        return build;


    }

    // 订单支付
    @Override
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) {
        // 1.直接修改订单状态
        Orders ordersDB = ordersMapper.findByNumber(ordersPaymentDTO.getOrderNumber());
        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        ordersMapper.update(orders);
        
        //===================================通知商家: 新订单来了===========================//
        //1. 构建消息对象
        Map<String,Object> map =new HashMap<String,Object>();
        map.put("type",1);
        map.put("orderId",ordersDB.getId());
        map.put("content","订单号：" + ordersPaymentDTO.getOrderNumber());
        //2 对象转JSON
        String json = JSON.toJSONString(map);
        //3. 调用websocket终端,发送消息给浏览器
        webSocketServer.sendToAllClient(json);
        //===================================通知商家: 新订单来了===========================//

        // 2. 返回一个空结果
        return new OrderPaymentVO();
    }


    //历史订单查询    //订单搜索
    @Override
    public PageBean findByPage(OrdersPageQueryDTO ordersPageQueryDTO) {
        //1. 开启分页
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        //2. 执行查询
        List<OrderVO> voList = ordersMapper.findList(ordersPageQueryDTO);
        Page<OrderVO> page = (Page<OrderVO>) voList;

        //3. 为每个订单填充订单详情
        if (CollectionUtil.isNotEmpty(page.getResult())) {
            for (OrderVO orderVO : page.getResult()) {
                //3-1 调用orderDetailMapper根据订单id查询详情列表
                List<OrderDetail> details = orderDetailMapper.findByOrderId(orderVO.getId());
                //3-2 将detail封装到vo
                orderVO.setOrderDetailList(details);
                //3-3 新增订单明细拼接字符串
                StringBuilder stringBuilder = new StringBuilder();
                if (CollectionUtil.isNotEmpty(details)) {
                    for (OrderDetail detail : details) {
                        stringBuilder.append(detail.getName()).append("x").append(detail.getNumber()).append(";");
                    }
                }
                orderVO.setOrderDishes(stringBuilder.toString());
            }
        }
        //4. 返回结果
        return new PageBean(page.getTotal(), page.getResult());
    }

    //订单详情
    @Override
    public OrderVO findById(Long orderId) {

        //1. 根据订单id从订单表查询订单基本信息
        OrderVO orderVO = ordersMapper.findById(orderId);

        //2. 根据订单id从订单详情表查询订单详情列表
        List<OrderDetail> orderDetailList = orderDetailMapper.findByOrderId(orderId);

        //3. 组装返回vo
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    //取消订单
    @Override
    public void cancelById(Long orderId) {

        //1.根据订单id查询
        OrderVO orderVO = ordersMapper.findById(orderId);
        //2.判断订单状态
        if (orderVO.getStatus() > 2) { //3.已接单 4.派送中 5.已完成 6.已取消
            throw new RuntimeException("订单状态不正确");
        }
        //3.修改订单状态
        //3-1.修改订单状态
        Orders orders = Orders.builder()
                .id(orderId)
                .status(6)//取消
                .cancelReason("用户取消订单")
                .cancelTime(LocalDateTime.now())
                .build();


        //3-2.如果是已支付的订单,需要发起微信退款的请求
        if (orderVO.getPayStatus() == 1) {
            try {
                orders.setPayStatus(2);//退款
            } catch (Exception e) {
                throw new BusinessException("微信退款失败,联系商家");
            }
        }
        //3-3.调用mapper更新
        ordersMapper.update(orders);
    }

    //再来一单
    @Override
    public void repetitionById(Long orderId) {
        //1.清理当前用户购物车中
        shoppingCartService.clean();
        //2.根据订单id查询订单明细
        List<OrderDetail> orderDetailList = orderDetailMapper.findByOrderId(orderId);
        //3.遍历购物车明细,重新加入购物车
        if (CollectionUtil.isNotEmpty(orderDetailList)) {
            for (OrderDetail orderDetail : orderDetailList) {
                //3-1 每一个订单详情--->购物车1项
                ShoppingCart shoppingCart = BeanUtil.copyProperties(orderDetail, ShoppingCart.class, "id");
                //3-2 补齐参数
                shoppingCart.setUserId(UserHolder.get());
                shoppingCart.setCreateTime(LocalDateTime.now());
                //3-3 保存到购物车表
                shoppingCartService.save(shoppingCart);
            }
        }
    }

    //各个状态的订单详情
    @Override
    public OrderStatisticsVO statistics() {
        //查询各个状态  2待接单 3已接单 4派送中
        int toBeConfirmedCount = ordersMapper.findList(OrdersPageQueryDTO.builder().status(2).build()).size();
        int confirmedCount = ordersMapper.findList(OrdersPageQueryDTO.builder().status(3).build()).size();
        int deliveryInProgressCount = ordersMapper.findList(OrdersPageQueryDTO.builder().status(4).build()).size();

        //返回
        return OrderStatisticsVO.builder()
                .toBeConfirmed(toBeConfirmedCount)
                .confirmed(confirmedCount)
                .deliveryInProgress(deliveryInProgressCount)
                .build();
    }

    //接单
    @Override
    public void confirm(OrdersConfirmDTO dto) {

        //1.查询订单信息
        Orders orderVO = ordersMapper.findById(dto.getId());
        //2.判断订单状态
        if (orderVO.getStatus() != 2) {//待接单
            throw new RuntimeException("订单状态不正确");
        }
        //3.修改订单状态
        //3-1.修改订单状态
        Orders orders = Orders.builder()
               .id(dto.getId())
               .status(3) //已接单
               .build();

        //3-2.调用mapper更新
        ordersMapper.update(orders);
    }

    //拒单
    @Override
    public void rejection(OrdersRejectionDTO dto) {
    //1.查询订单信息
        Orders orderVO = ordersMapper.findById(dto.getId());
        //2.判断订单状态
        if (orderVO.getStatus() != 2) {//待接单
            throw new RuntimeException("订单状态不正确");
        }
        //3.修改订单状态
        //3-1.修改订单状态
        Orders orders = Orders.builder()
                .id(dto.getId())
                .status(6) //商家拒单
                .cancelReason("商家拒单")
                .rejectionReason(dto.getRejectionReason())
                .cancelTime(LocalDateTime.now())
                .build();

        //3-2.如果是已支付的订单,需要发起微信退款的请求
        if (orderVO.getPayStatus() == 1) {
            try {
                orders.setPayStatus(2);//退款
            } catch (Exception e) {
                throw new BusinessException("微信退款失败,联系商家");
            }
        }
        //3-3.调用mapper更新
        ordersMapper.update(orders);
    }

    //取消订单
    @Override
    public void cancel(OrdersRejectionDTO dto) {
        //1.查询订单信息
        Orders orderVO = ordersMapper.findById(dto.getId());
        //2.判断订单状态
        if (orderVO.getStatus() >4) { //1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
            throw new RuntimeException("订单状态不正确");
        }
        //3.修改订单状态
        //3-1.修改订单状态
        Orders orders = Orders.builder()
                .id(dto.getId())
                .status(6) //取消订单
                .rejectionReason(dto.getRejectionReason())//拒绝原因
                .cancelTime(LocalDateTime.now())
                .build();
        //3-2商家取消订单时，如果用户已经完成了支付，需要为用户退款
        if (orderVO.getPayStatus() == 1) {
            try {
                orders.setPayStatus(2);//退款
            } catch (Exception e) {
                throw new BusinessException("微信退款失败,联系商家");
            }
        }
        //4.调用mapper更新
        ordersMapper.update(orders);
    }

    //派送订单
    @Override
    public void delivery(Long id) {
        //1.查询订单信息
        Orders orderVO = ordersMapper.findById(id);
        //2.判断订单状态
        if (orderVO.getStatus() != 3) {//待接单
            throw new RuntimeException("订单状态不正确");
        }
        //3.修改订单状态
        //3-1.修改订单状态
        Orders orders = Orders.builder()
                .id(id)
                .status(4) //派送中
                .build();

        //3-2.调用mapper更新
        ordersMapper.update(orders);
    }

    //完成订单
    @Override
    public void complete(Long id) {
        //1.查询订单信息
        Orders orderVO = ordersMapper.findById(id);
        //2.判断订单状态完成订单完成订单
        if (orderVO.getStatus() != 4) {//派送中
            throw new RuntimeException("订单状态不正确");
        }
        //3.修改订单状态
        //3-1.修改订单状态
        Orders orders = Orders.builder()
                .id(id)
                .status(5) //已完成
                .deliveryTime(LocalDateTime.now())//送达时间
                .build();

        //3-2.调用mapper更新
        ordersMapper.update(orders);
    }

    //催单
    @Override
    public void reminder(Long orderId) {
        //1.查询订单信息
        Orders orderVO = ordersMapper.findById(orderId);

        if (orderVO == null || orderVO.getStatus() != 2){
            throw new BusinessException("状态错误");
        }
        //2. 构建消息对象
        Map<String,Object> map =new HashMap();
        map.put("type",2);
        map.put("orderId",orderId);
        map.put("content","订单号：" + orderVO.getNumber());
        //3 对象转JSON
        String json = JSON.toJSONString(map);
        //4. 调用websocket终端,发送消息给浏览器
        webSocketServer.sendToAllClient(json);

    }


}
